<?php
/*
+ --------------------------------------------------- +
|  Ineo Article Manager - Version 2.x
|  Copyright 2006-2007, Dan Cryer and William McGann
+ --------------------------------------------------- +

Ineo Article Manager is free software; you can redistribute it and/or modify
it under the terms of version 3 of the GNU General Public License as published by
the Free Software Foundation.

Ineo Article Manager is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Ineo; see the file License.txt.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

*/

/**
* Ineo - Libraries - General
*  
* This library handles various general functions for Ineo,
* including sending of watchlist alerts, logging, etc.
*
* @package		Ineo
* @subpackage   Libraries
* @author		Dan Cryer & William McGann
* @copyright	Dan Cryer & William McGann
* @version		1.0.0
*/
class ineo_lib_global
{
	var $text_id_prefix;
	
	/**
	* Constructor:
	*/
	function ineo_lib_global( &$ineo )
	{
		$this->core     =& $ineo;
		$this->ipsclass =& $ineo->ipsclass;
	}
	
	/**
	* Ineo - Standard Error Handler
	*/
	function error( $error_title = null, $error_message = null , $link = null )
	{	
		if( $link == null )
		{
			$link = array( 'lang' =>'ineo_return_to_idx' , 'link' => 'autocom=ineo' );
		}
		
		$error_message   = empty($error_message) ? $this->core->error : $error_message;
		$error_title     = empty($error_title) ? $this->ipsclass->lang['ineo_error_title'] : $error_title;

		$message = empty($this->ipsclass->lang[$error_message]) ? $error_message : $this->ipsclass->lang[$error_message];
		$title   = empty($this->ipsclass->lang[$error_title]  ) ? $error_title : $this->ipsclass->lang[$error_title];

		$error = array('title'   => $title,'message' => $message,'link'    => $link,);

		$this->core->out .= $this->core->templates['global']->general_error( $error );
	}

	/**
	* Sort've like sprintf, except it replaces named items, such as &name or &date
	* Expects an array of ( 'find' => 'replace' ).
	*
	* Added: 1.1 ( 18th Sep 06 )
	*/
	function my_sprintf( $string , $replacements )
	{
		foreach( $replacements as $find => $replace )
		{
			$string = str_replace($find,$replace,$string);
		}

		return $string;
	}
	
	/**
	* Send watchlist alerts for an article/category update:
	*/
	function watchlist_alert( $watch_id , $watch_type , $data = '' )
	{
		// Load our PM user:
		$this->ipsclass->DB->simple_construct( array('select' => '*','from'   => 'members','where'  => 'name = \''.$this->ipsclass->vars['ineo_alert_user'].'\'',));
		$ams = $this->ipsclass->DB->simple_exec();

		// If the user does not exist, they can't send a PM, can they?
		if( !$this->ipsclass->DB->get_num_rows() )
		{
			return;
		}

		$ams = $this->ipsclass->DB->fetch_row($ams);

		if( $watch_type == 1 )
		{
			// Article Specific Query:

			$watch['title'] = $this->ipsclass->lang['ineo_watch_article'];
			$watch['op']    = 'art';

			$query = array('select'   => 'w.* , a.article_title','from'     => array( 'ineo_watchlists' => 'w' ),'where'    => 'watch_type = 1 AND watch_id = ' . $watch_id,'add_join' => array(1 => array('type'     => 'left','from'     => array( 'ineo_articles' => 'a' ),'where'    => 'a.article_id = w.watch_id',)));

			$this->ipsclass->DB->simple_construct( $query );
		}
		else
		{

			$query = array('select' => '*','from'   => 'ineo_articles','where'  => 'article_id = ' . $data,);

			$this->ipsclass->DB->simple_construct( $query );
			$this->ipsclass->DB->simple_exec();
			$data = $this->ipsclass->DB->fetch_row();

			// Category Specific Query:

			$watch['title'] = $this->ipsclass->lang['ineo_watch_category'];
			$watch['op']    = 'cat';

			$query = array('select' => 'w.* , c.category_name','from'   => array( 'ineo_watchlists' => 'w' ),'where'  => 'watch_type = 2 AND watch_id = ' . $watch_id, 'add_join' => array( 1 => array( 'type' => 'left','from' => array( 'ineo_categories' => 'c' ),'where' => 'c.category_id = w.watch_id',)));
			$this->ipsclass->DB->simple_construct( $query );
		}

		$q = $this->ipsclass->DB->simple_exec();


		while( $res = $this->ipsclass->DB->fetch_row($q) )
		{
			// Set options:
			$opts['save_only'] = false;
			$opts['orig_id']   = 0;
			$opts['preview']   = false;
			$opts['track']     = 0;
			$opts['add_sent']  = false;
			$opts['hide_cc']   = true;

			// Load class:
			$msg =& $this->ipsclass->load_class('sources/lib/func_msg.php','func_msg');
			$msg->init();

			// Set to ID:
			$msg->to_by_id = $res['watch_user'];
			$msg->from_member =& $ams;
			$msg->msg_title = $this->ipsclass->lang['ineo_alert_title'];

			$data = array_merge( $res , $data , $this->ipsclass->member );

			$msg->msg_post = $this->do_replacements($this->ipsclass->lang['ineo_' . $watch['op'] . '_alert'] , $data );
			$msg->send_pm($opts);
		}

	}
	
	/**
	* Replaces... stuff... in the watchlist PM's.
	*/
	function do_replacements( $msg , $data )
	{
		$data['article_link']  = $this->core->base_url . 'showarticle=' . $data['watch_id'];
		$data['category_link'] = $this->core->base_url . 'showcat=' . $data['watch_id'];

		foreach( $data as $key => $val )
		{
			$msg = str_replace( '{' . $key . '}' , $val , $msg );
		}

		return $msg;
	}

	/**
	* Simple 'nuff. Inserts a row in the ineo_logs table with a quick note regarding the action.
	*/
	function add_log($act, $code, $note)
	{
		$insert = array('member_id' => $this->ipsclass->member['id'],'act' => $act,'code' => $code,'note' => $note,'time' => time(),'ip_address' => $this->ipsclass->input['IP_ADDRESS']);
		$this->ipsclass->DB->do_insert('ineo_logs', $insert, 1);
	}
	
	/**
	* Builds the base breadcrumb navigation:
	*/
	function build_nav()
	{
		$this->nav_add( $this->ipsclass->vars['ineo_page_title'] , '' );

		if( !empty($this->ipsclass->input['mod']) and $this->ipsclass->input['mod'] == 'category' )
		{
			$this->nav_add( $this->ipsclass->lang['ineo_categories'] , 'mod=category&op=catlist' );
		}

		if( !empty($this->ipsclass->input['op']) and  $this->ipsclass->input['op'] == 'new' )
		{	
			$this->nav_add( $this->ipsclass->lang['ineo_new_article'] , 'mod=article&op=new_art' );
		}
	}
	
	/**
	* Adds an item to the breadcrumb navigation:
	*/
	function nav_add( $title , $link, $override = 0 )
	{
		$prefix = ( $override == 0 ) ? $this->core->base_url : '' ;
		$this->core->nav[] = "<a href='{$prefix}{$link}'>{$title}</a>";
	}
	
	/**
	* Creates a text id from a string. Intended for article titles.
	* Added 1.1
	*/
	function make_text_id( $title, $category )
	{
		$title = $this->_clean_title_for_id( $title );
		
		if ( $category != 0 )
		{
			$this->_build_category_prefix( $category );
			$title = $this->text_id_prefix . $title;
		}
		
		return $title;
	}
	
	/**
	* Creates a prefix with all parent/grandparent/greatgrandparent (a-hyuk) categories.
	*/
	function _build_category_prefix( $category )
	{
		$this->text_id_prefix = $this->_clean_title_for_id( $this->ipsclass->cache['ineo_cats'][$category]['info']['category_name'] ) . '/' . $this->text_id_prefix;
		
		if ( $this->ipsclass->cache['ineo_cats'][$category]['info']['category_parent'] == 0 )
		{
			return true;
		}
		
		$this->_build_category_prefix( $this->ipsclass->cache['ineo_cats'][$category]['info']['category_parent'] );
	}
	
	/**
	* Clean a string, returning a suitable text id.
	*/
	function _clean_title_for_id( $title, $to_lower = 1 )
	{
		$title = str_replace( '&#39;', '\'', $title );
		$title = html_entity_decode( $title );
		$title = preg_quote( str_replace( ' ', '-', $title ) );
		$title = preg_replace( "/<(.*)>/", '', $title );
		$title = preg_replace( "/([^a-zA-Z0-9\(\)\_\-\/])/", '', $title );
		$title = preg_replace( "/[\-]+/", '-', $title );
		$title = ( $to_lower == 1 ) ? strtolower( $title ) : $title ;
		
		return $title;
	}
	
	/**
	* Creates URL for viewing an article.
	* Added 1.1
	*/
	function make_article_url( $id, $title )
	{
		if ( $this->ipsclass->vars['ineo_friendly_enable'] == 1 )
		{
			$slash = ( substr( $this->ipsclass->vars['ineo_friendly_base'], -1, 1 ) == '/' ) ? '' : '/' ;
			$url = $this->ipsclass->vars['ineo_friendly_base'] . $slash . $title . $this->ipsclass->vars['ineo_friendly_suffix'];
		}
		else
		{
			$url = $this->ipsclass->base_url . 'autocom=ineo&showarticle=' . $id;
		}
		return $url;
	}
	
	
	function category_dropdown( $default = 0, $include_root = false )
	{
		$categories =& $this->ipsclass->cache['ineo_cats'];
			
		$items = '<select name="category">';
		
		if( $include_root )
		{
			$selected = ( 0 == $default ) ? ' selected="selected"' : '';
			
			$items .= "<option value='0' style='font-weight: bold'>{$this->ipsclass->lang['ineo_root_category']}</option>\n";
			
			$depth = '--';
		}
		else
		{
			$depth = '';
		}
		
		foreach( $categories as $cat )
		{
			if($cat['info']['category_parent'] == 0)
			{
				$selected = ( $cat['info']['category_id'] == $default ) ? ' selected="selected"' : '';
				
				$items .= "<option value='{$cat['info']['category_id']}{$selected}'>{$depth}{$cat['info']['category_name']}</option>\n";
				
				$items .= $this->category_dropdown_internal($cat['children'], $depth.'--', $default);
			}
		}
		
		$items .= '</select>';
		
		return $items;
	}
	
	function category_dropdown_internal( $categories, $depth = "", $default )
	{
		$items = '';
		
		foreach( $categories as $cat )
		{
			$selected = ( $cat['info']['category_id'] == $default ) ? ' selected="selected"' : '';
			
			$items .= "<option value='{$cat['info']['category_id']}'{$selected}>{$depth} {$cat['info']['category_name']}</option>\n";
				
			$items .= $this->category_dropdown_internal($cat['children'],$depth.'--',$default);
		}
		
		return $items;
	}
	
	function keyword_replace($string)
	{
		$string = str_replace('style_images/<#IMG_DIR#>',$this->ipsclass->vars['img_url'],$string);
		
		return $string;
	}
	
	function generate_csrf_key( $action )
	{
		$mid = md5($this->ipsclass->member['member_login_key']);
		$my  = date('m-Y');
		
		return md5( $mid . $my . $action );
	}
	
	function create_discussion_topic( $article_id )
	{
		$article_id = intval( $article_id );
		
		// set the forum id:
		
		$forum_id = intval($this->ipsclass->vars['ineo_topic_forum']);
		
		// set topic description:
		
		$topic_desc = $this->ipsclass->lang['ineo_topic_desc'];
		
		// load article data:
		
		$array = array(
			'select'   => 'a.*,c.*',
			'from'     => array('ineo_articles'=>'a'),
			'add_join' => array(
					1 => array(
					'type'  => 'left',
					'from'  => array('ineo_content'=>'c'),
					'where' => 'c.content_article = a.article_content',
					),
				),
			'where'  => 'a.article_id = ' . $article_id,
			);
			
		$this->ipsclass->DB->simple_construct( $array );
		$this->ipsclass->DB->simple_exec();
		
		$arti = $this->ipsclass->DB->fetch_row();

		// set topic title:
		$topic_title = $arti['article_title'];
		
		// make sure that no other topics exist:
		
		if( !empty($arti['article_tid']) )
		{
			$array = array('select' => '*',
			               'from'   => 'topics',
			               'where'  => 'tid = ' . $arti['article_tid']);
			
			$this->ipsclass->DB->simple_construct( $array );
			$this->ipsclass->DB->simple_exec();

			if( $this->ipsclass->DB->get_num_rows() != 0 )
			{
				$tpc = $this->ipsclass->DB->fetch_row();
				
				return array('id'=>$arti['article_tid'],'title'=>$tpc['title']);
			}
		}
		
		// set the author id:
		
		$author_id = $this->ipsclass->member['id'];
		
		if( $this->ipsclass->member['mgroup'] == $this->ipsclass->vars['guest_group'] )
		{
			$author_id = $arti['article_author'];
		}
		
		// set the topic content:
		
		$topic_content = "<a href='{$this->ipsclass->base_url}autocom=ineo&showarticle={$article_id}'>{$arti['article_title']}</a>";
		
		// set the topic title:
		$topic_title = $arti['article_title'];
		
		
		// create the topic:
		$id = $this->create_ipb_topic( $forum_id, $author_id, $topic_title, $topic_content, $topic_desc );
		
		if( !is_numeric($id) )
		{
			return $id;
		}
				
		// update article row in db:
		$this->ipsclass->DB->do_update( 'ineo_articles' , array( 'article_tid' => $id ) , 'article_id = ' . $this->ipsclass->input['id'] );
		
		return array('id'=>$id,'title'=>$topic_title);
	}
	
	function create_ipb_topic( $forum_id, $author_id, $topic_title, $topic_content, $topic_desc = '' )
	{
		// Clean up the incoming variables:
		
		$forum_id  = intval($forum_id);
		$author_id = intval($author_id);
	
		// Check incoming:
		
		if( empty($forum_id) or empty($author_id) or empty($topic_title) or empty($topic_content) )
		{
			return 'error:invalid_data';
		}
				
		// First, check the forum we're trying to post to actually exists:
		
		$check = array('select' => 'id','from' => 'forums','where' => 'id = \''.$forum_id.'\'');
		$this->ipsclass->DB->simple_construct( $check );
		$this->ipsclass->DB->simple_exec();
		
		if( !$this->ipsclass->DB->get_num_rows() )
		{
			return 'error:invalid_forum';
		}
		
		// Load topics & posts API:	
		
		require_once( ROOT_PATH . 'sources/api/api_topics_and_posts.php' );
		$api           = new api_topics_and_posts();
		$api->ipsclass =& $this->ipsclass;
		
		// Set it up:
		
		$api->set_author_by_id( $author_id );
		$api->set_forum_id( $forum_id );
		$api->set_topic_title( $topic_title );
		$api->set_topic_description( $topic_desc );
		$api->set_post_content( $topic_content );
		$api->set_topic_state( 'open' );
		
		// Create the topic:
		
		if( !$api->create_new_topic() )
		{
			return 'fail:create';
		}
		
		// Get topic ID to return:
		
		$topic_id = $api->topic_id;
		
		return $topic_id;
	}
	
	// UTF-8 Fixing
	function ajax_utf8_safe()
	{
		// Make sure the charset is set:
		$this->ipsclass->vars['gb_char_set'] = $this->ipsclass->vars['gb_char_set'] ? $this->ipsclass->vars['gb_char_set'] : 'iso-8859-1';
		
		// Make sure it is also passed via header:
		@header( "Content-type: text/html;charset={$this->ipsclass->vars['gb_char_set']}" );
	}
}

?>